//  Code adapted from "Windows Phone 7 Game Development" by Adam Dawes
//  Original code by Adam Dawes

using System;
using System.Collections.Generic;
using System.Text;

namespace YEngineLib.HighScores
{
    public class YHighScoreTable
    {
        // A list inside which all of the entries in the table will be stored
        private List<YHighScoreEntry> _scoreEntries;
        // The number of entries to store in the table
        private int _tableSize;

        //-------------------------------------------------------------------------------------
        // Class constructor

        /// <summary>
        /// Class constructor. Initialize the table with the specified number of entries.
        /// Scope is internal so external code cannot create instances.
        /// </summary>
        internal YHighScoreTable(int tableSize, string tableDescription)
        {
            // Store the parameter values
            Description = tableDescription;
            _tableSize = tableSize;

            // Reset the table
            Clear();
        }

        //-------------------------------------------------------------------------------------
        // Property access

        /// <summary>
        /// Returns a read-only list of all the entries in the table
        /// </summary>
        public System.Collections.ObjectModel.ReadOnlyCollection<YHighScoreEntry> Entries
        {
            get
            {
                // Ensure the list is returned read only so that it cannot
                // be interfered with from outside
                return _scoreEntries.AsReadOnly();
            }
        }

        /// <summary>
        /// Return the table description
        /// </summary>
        public string Description { get; set; }

        //-------------------------------------------------------------------------------------
        // Class functions

        /// <summary>
        /// Create/reset the initial empty table
        /// </summary>
        public void Clear()
        {
            // Create the score list
            _scoreEntries = new List<YHighScoreEntry>();

            // Add an entry for each position specified in the table
            for (int i = 0; i < _tableSize; i++)
            {
                _scoreEntries.Add(new YHighScoreEntry());
            }
        }

        /// <summary>
        /// Add a new entry to the highscore table.
        /// </summary>
        /// <param name="Name">The Name for the new entry</param>
        /// <param name="score">The Score for the new entry</param>
        /// <returns>Returns the HighScoreEntry object added, or if the score
        /// was not high enough to feature in the list, returns null.</returns>
        public YHighScoreEntry AddEntry(string name, int score)
        {
            return AddEntry(name, score, DateTime.Now);
        }

        /// <summary>
        /// An internal overload of AddEntry which also allows the entry date
        /// to be specified. This is used when loading the scores from the
        /// storage file.
        /// </summary>
        internal YHighScoreEntry AddEntry(string name, int score, DateTime date)
        {
            //int rank = ScoreRank(score);

            //if (rank == -1)
            //    return null;

            // Create and initialize a new highscore entry
            YHighScoreEntry entry = new YHighScoreEntry();
            entry.Name = name;
            entry.Score = score;
            entry.Date = date;

            //_scoreEntries.Insert(rank, entry);
            // Add to the table
            _scoreEntries.Add(entry);

            // Sort into descending order
            _scoreEntries.Sort();//new YHighScoreEntry());

            // Limit the number of entries to the requested table size
            if (_scoreEntries.Count > _tableSize)
            {
                _scoreEntries.RemoveAt(_tableSize);
            }

            // Is our entry still in the list
            if (_scoreEntries.Contains(entry))
            {
                // Yes, so return the entry object
                return entry;
            }
            // No, so return null
            return null;
        }

        public YHighScoreEntry InsertEntry(string name, int score)
        {
            int rank = ScoreRank(score);

            if (rank == -1)
                return null;

            // Create and initialize a new highscore entry
            YHighScoreEntry entry = new YHighScoreEntry();
            entry.Name = name;
            entry.Score = score;
            entry.Date = DateTime.Now;// date;

            _scoreEntries.Insert(rank, entry);

            // Limit the number of entries to the requested table size
            if (_scoreEntries.Count > _tableSize)
            {
                _scoreEntries.RemoveAt(_tableSize);
            }

            // Is our entry still in the list
            if (_scoreEntries.Contains(entry))
            {
                // Yes, so return the entry object
                return entry;
            }
            // No, so return null
            return null;
        }

        /// <summary>
        /// Determines whether this score is high enough to be added to the table
        /// </summary>
        /// <param name="score">The score to test</param>
        /// <returns>Return true if the score is high enough, false if it is not</returns>
        public bool ScoreQualifies(int score)
        {
            return (score > _scoreEntries[_tableSize - 1].Score);
        }

        /// <summary>
        /// Determines this score's rank in the table
        /// </summary>
        /// <param name="score">The score to test</param>
        /// <returns>Returns the index the score will be put at, -1 if it doesn't rank</returns>
        public int ScoreRank(int score)
        {
            int rank = -1;

            for (int i = _tableSize - 1; i >= 0; i--)
            {
                if (score < _scoreEntries[i].Score)
                {
                    rank = i + 1;
                    break;
                }
            }

            // Test for greater than ALL
            if (score >= _scoreEntries[0].Score)
                return 0;

            if (rank >= _tableSize)
                rank = -1;

            return rank;
        }

    }
}